
--# BaseObject
--以后版本的UI控件都需要这个基类
BaseObject = class()
function BaseObject:init(x,y)
 self.x = x
 self.y = y
 self.fatherObject = nil
end
function BaseObject:setFatherObject(object)
 self.fatherObject = object
end
function BaseObject:setProperty(property)
 for k,v in pairs(property) do
 self[k] = v
 end
end
function BaseObject:draw()
 
end
function BaseObject:touched(touch)
 
end
--# Multiplayer
--multiplayer library follows
--# Multiplayer
 
local socket = require("socket")
 
Multiplayer = class()
 
function Multiplayer:init(dcb, ccb)
    self.my_ip, self.my_port = self:getLocalIP(), 5400
    self.peer_ip, self.peer_port = nil, self.my_port
 
    self.client = socket.udp()
    self.client:settimeout(0)
 
    self.connected = false
    self.is_host = false
    self.searching = false
 
    self.dataCallback = dcb or function() end
    self.connectedCallback = ccb or function() end
end
 
-- Returns this iPad's local ip
function Multiplayer:getLocalIP()
    local randomIP = "192.167.188.122"
    local randomPort = "3102" 
    local randomSocket = socket.udp() 
    randomSocket:setpeername(randomIP,randomPort) 
 
    local localIP, somePort = randomSocket:getsockname()
 
    randomSocket:close()
    randomSocket = nil
 
    return localIP
end
 
-- Set the connected status and call the connection callback if needed
function Multiplayer:setConnectedVal(bool)
    self.connected = bool
 
    if self.connected then
        self.connectedCallback()
    end
end
 
function Multiplayer:setHostVal(bool)
    self.is_host = bool
end
 
-- Prepare to be the host
function Multiplayer:hostGame()
    print("Connect to " .. self.my_ip .. ":" .. self.my_port)
 
    self.client:setsockname(self.my_ip, self.my_port)
 
    self:setConnectedVal(false)
    self.is_host = true
    self.searching = false
end
 
-- Find a host
function Multiplayer:findGame()
    print("Searching for games...")
 
    self.searching = true
 
    local ip_start, ip_end = self.my_ip:match("(%d+.%d+.%d+.)(%d+)")
    for i = 1, 255 do
        if i ~= tonumber(ip_end) then
            tween.delay(0.01 * i, function()
                self.client:setsockname(ip_start .. i, self.my_port)
                self.client:sendto("connection_confirmation", ip_start .. i, self.my_port)
            end)
        end
    end
end
 
-- Prepare to join a host
function Multiplayer:joinGame(ip, port)
    self.peer_ip, self.peer_port = ip, port
 
    self.client:setsockname(ip, port)
 
    self.is_host = false
    self.searching = false
 
    self:sendData("connection_confirmation")
end
 
-- Send data to the other client
function Multiplayer:sendData(msg_to_send)
    if self.peer_ip then
        self.client:sendto(msg_to_send, self.peer_ip, self.peer_port)
    end
end
 
-- Check for data received from the other client
function Multiplayer:checkForReceivedData()
    local data, msg_or_ip, port_or_nil = self.client:receivefrom()
    if data then
            -- Store the ip of this new client so you can send data back
            self.peer_ip, self.peer_port = msg_or_ip, port_or_nil
 
            if not self.connected and data == "connection_confirmation" then
                self:sendData("connection_confirmation")
                self:setConnectedVal(true)
            end
 
            -- Call callback with received data
            if data ~= "connection_confirmation" then
                self.dataCallback(data)
            end
    end
end
 
function Multiplayer:update()
    self:checkForReceivedData()
end
--# PrBar
-- ProcessBar
-- Ver 1.1
-- Author:bk194232658
-- 进度条
ProcessBar = class()
function ProcessBar:init(x,y,width,height)
 self.x = x
 self.y = y
 self.width = width
 self.height = height
 self.backColor = color(54, 54, 54, 112)
 self.color = color(39, 38, 242, 121)
 self.frameWidth = 3
 self.frameColor = color(46, 46, 46, 152)
 self.percentage = 1
 self.posMode = CENTER
end
function ProcessBar:draw()
 if self.percentage < 0 then self.percentage = 0 return end
 if self.percentage > 1 then self.percentage = 1 end
 pushStyle()
 rectMode(CORNER)
 if self.frameWidth > 0 then
 strokeWidth(self.frameWidth)
 stroke(self.frameColor)
 else
 noStroke()
 end
 fill(self.backColor) 
 if self.posMode == CENTER then
 rect(self.x - self.width / 2,self.y - self.height / 2,self.width,self.height)
 else
 rect(self.x,self.y,self.width,self.height)
 end
 stroke(0, 0, 0, 0)
 fill(self.color)
 if self.posMode == CENTER then
 rect(self.x - self.width / 2,self.y - self.height / 2,self.width * self.percentage,self.height)
 else
 rect(self.x,self.y,self.width * self.percentage,self.height)
 end
 popStyle()
end
function ProcessBar:touched(touch)
 
end
--# Slider
--[[
80%仿UIKit 滑动条
v1.0 By SoulWINTER
---------------------
使用方法：
在setup()中写
xxx=UISlider()
xxx:init(长度（像素），最小值，最大值，位置x，位置y，据开始多少像素）
例如：test = UISlider() test:init(500,0,1,WIDTH/2,HEIGHT/2,50)
在draw()中写
xxx（你刚才取的名字）:draw()
例如：test:draw()
在touched中写
xxx:touched(touch)
例如：test:touched(touch)
xxx.num 就是滑动所得值
--]]
UISlider = class()
function UISlider:init(length,min,max,x,y,startPos) 
    self.length = length
    self.min = min
    self.max = max
    self.pos = vec2(x,y)
    self.buttonPos = startPos
    self.isTouching = false
    self.num = 0
end
function UISlider:draw() 
    stroke(0, 102, 255, 255)
    strokeWidth(2)
    line(self.pos.x-self.length/2,self.pos.y,self.pos.x-self.length/2+self.buttonPos,self.pos.y)
    stroke(220, 208, 208, 255) 
    line(self.pos.x-self.length/2+self.buttonPos,self.pos.y,self.pos.x+self.length/2,self.pos.y)
    noStroke()
    fill(193, 208, 205, 108)
    ellipse(self.pos.x-self.length/2+self.buttonPos,self.pos.y-3,30,30) 
    strokeWidth(1)
    stroke(199, 209, 206, 255)
    fill(255, 255, 255, 255)
    ellipse(self.pos.x-self.length/2+self.buttonPos,self.pos.y,30,30) 
    self.num = self.buttonPos*((self.max-self.min)/self.length)
    --text("hello",self.pos.x,sself.pos.y)
end
function UISlider:touched(touch)
    if touch.state == BEGAN and touch.x >= (self.pos.x-self.length/2+self.buttonPos)-15 and touch.x <= self.pos.x-self.length/2+self.buttonPos+15 and touch.y >= self.pos.y-15 and touch.y <= self.pos.y+15 then
        self.isTouching = true
        
    end
    
    if touch.state ~= ENDED and self.isTouching == true then 
        if touch.x-(self.pos.x-self.length/2)>=0 and touch.x-(self.pos.x-self.length/2)<=self.length then
            self.buttonPos = touch.x-(self.pos.x-self.length/2)
        end
        if touch.x-(self.pos.x-self.length/2)<=0 then
            self.buttonPos = 0
        end
        if touch.x-(self.pos.x-self.length/2)>=self.length then
            self.buttonPos = self.length
        end
    end
    
    if touch.state == ENDED then
        self.isTouching = false
    end
    
    
end
--# TextBox
-- TextBox
-- Ver.Beta 0.14

TextBox = class(BaseObject)

function TextBox:init(x,y,width,height,text)
    BaseObject.init(self,x,y)
    self.width = width
    self.height = height
    self.backColor = color(255, 255, 255, 255)
    self.focusframeColor = color(0, 133, 255, 255)
    self.frameColor = color(150, 150, 150, 255)
    self.textColor = color(0, 0, 0, 255)
    self.frameWidth = 1.8
    self.posMode = CENTER
    self.multiLine = false
    self.text = text or ""
    self.font = nil
    self.fontSize = 20
    self.touchid = 0
    self.inputing = false
    self.cursorColor = color(0, 153, 255, 0)
    self.cursorWidth = 2.5
    self.cursorPos = 0
    self.blinkTime = 0.5 --光标闪烁时间
    self.blinkInterval = 40 --光标闪烁间隔
    self.blinkTween = nil
    self.time = 0
    self.showingCursor = false
    self.showCursor = true
    self.maxLength = -1
end

function TextBox:draw()
    local x,y = self.x,self.y
    local w,h = self.width,self.height
    local fw = self.frameWidth
    pushStyle()
    smooth()
    if self.posMode == CENTER then
        x,y = x - w / 2,y - h / 2
    end
    if isKeyboardShowing() == false then
        self.inputing = false
    end
    
    rectMode(CORNER)
    fill(self.backColor)
    if self.frameWidth > 0 then
        strokeWidth(fw)
        if self.inputing then
            stroke(self.focusframeColor)
        else
            stroke(self.frameColor)
        end
    else
        noStroke()
    end
    
    rect(x,y,w,h)
    
    clip(x + fw,y + fw,w - fw,h - fw)
    
    font(self.font or "HelveticaNeue")
    fontSize(self.fontSize)
    textMode(CORNER)
    fill(self.textColor)
    
    local tw,th = textSize(self.text)
    if self.multiLine then
        textWrapWidth(self.width - 2 * fw)
    else
        textWrapWidth(0)
        text(self.text,x + fw,y + h / 2 - th / 2)
    end
    
    if isKeyboardShowing() == false then
        self.inputing = false
    end
    
    if self.inputing then
        if self.showingCursor == true then
            self.time = self.time + 1
            if self.time >= self.blinkInterval then
                self.time = 0
                self.showingCursor = false
                self:blickCursor()
            end
        end
    else
        if self.blinkTween then
            tween.stop(self.blinkTween)
            self.blinkTween = nil
            self.showingCursor = false
            self.cursorColor.a = 0
        else
            self.showingCursor = false
            self.cursorColor.a = 0
        end
    end
    
    if self.showCursor then
        local newtext = string.sub(self.text,1,self.cursorPos)
        local ntw,nth = textSize(newtext)
        strokeWidth(self.cursorWidth)
        stroke(self.cursorColor)
        lineCapMode(SQUARE)
        if self.multiLine then
            
        else
            line(x + fw + ntw,y + h / 2 - nth / 2,x + fw + ntw,y + h / 2 + nth / 2)
        end
    end
    
    clip()
    popStyle()
end

function TextBox:blickCursor()
    if not self.inputing then return end
    self.blinkTween = tween(self.blinkTime,self.cursorColor,{a = 0},tween.easing.cubicOut,function()
                self.showingCursor = false
                self.blinkTween = tween(self.blinkTime,self.cursorColor,{a = 255},tween.easing.cubicOut,function()
                    self.blinkTween = nil
                    self.showingCursor = true
                end)
            end)
end

function TextBox:touched(touch)
    local x,y,width,height = self.x,self.y,self.width,self.height
    if self.posMode == CENTER then
        x,y = x - width / 2,y - height / 2
    end
    local isInBox = touch.x >= x and touch.y >= y and 
                touch.x <= x + width and touch.y <= y + height
    if isInBox then 
        if touch.state == BEGAN and self.touchid == 0 then
            if self.inputing == false then
                self.inputing = true
                showKeyboard()
                self.cursorPos = string.len(self.text)
                self:resetBlink()
            end
            self.touchid = touch.id
        elseif touch.state == ENDED then
            self.touchid = 0
        end
        return true
    end
    return false
end

function TextBox:resetBlink()
    if self.blinkTween then
        tween.stop(self.blinkTween)
        self.blinkTween = nil
    end
    self.showingCursor = true
    self.time = -20
    self.cursorColor.a = 255
end

function TextBox:keyboard(key)
    if not self.inputing then return false end
    if key == BACKSPACE then
        self.text = string.sub(self.text,1,string.len(self.text) - 1)
        self.cursorPos = math.max(self.cursorPos - 1,0)
    else
        if self.maxLength > -1 then
            if string.len(self.text) >= self.maxLength then
                return true
            end
        end
        if self.multiLine then
            self.text = self.text .. key
            self.cursorPos = self.cursorPos + 1
            self:resetBlink()
        else
            if key == "\n" then
                self.inputing = false
                hideKeyboard()
            else
                self.text = self.text .. key
                self.cursorPos = self.cursorPos + 1
                self:resetBlink()
            end
        end
    end
    return true
end

--# UISwitch
UISwitch = class()
------------------------------------------
--写于2016.8.1 晚 9:15 作者：破晓_年华----
--使用时请保留此条信息--------------------
------------------------------------------
function UISwitch:init(x,y)
    -- you can accept and set parameters here
    self.x = x
    self.y = y
    self.stroke=color(230, 230, 230, 255)
    self.lineStroke=color(233, 233, 233, 255)
    self.backColor=color(240, 240, 240, 255)
    self.color = color(24, 232, 7, 255)
    self.buttonColor = color(255, 255, 255, 255)
    self.state=false
    self.buttonX=self.x-10
    self.nowColor={r=self.backColor.r,g=self.backColor.g,b=self.backColor.b}
    --width 52 height 32
    self.isTweening=false
    self.t={0.01,self.nowColor,{r=self.backColor.r,g=self.backColor.g,b=self.backColor.b}}
end

function UISwitch:draw()
    -- Codea does not automatically call this method
    strokeWidth(1)
    clip(self.x-26,self.y-16,16,32)
    fill(self.nowColor.r,self.nowColor.g,self.nowColor.b)
    stroke(self.stroke)
    ellipse(self.x-10,self.y,32)
    clip(self.x+10,self.y-16,16,32)
    ellipse(self.x+10,self.y,32)
    clip()
    stroke(self.lineStroke)
    strokeWidth(0)
    rect(self.x-11,self.y-14.5,22,30)
    strokeWidth(1.5)
    line(self.x-10.5,self.y-14.65,self.x+10.5,self.y-14.65)
    line(self.x-10.5,self.y+14.65,self.x+10.5,self.y+14.65)
    strokeWidth(1)
    fill(self.buttonColor)
    stroke(180, 180, 180, 255)
    sprite("Documents:Shadow",self.buttonX,self.y-2,30)
    ellipse(self.buttonX,self.y,30)
    if self.state==true and self.buttonX<self.x+10 then
        self.buttonX = self.buttonX + 2
    elseif self.state==false and self.buttonX>self.x-10 then
        self.buttonX = self.buttonX - 2
    end
    if self.state==true and not self.isTweening then
        self.isTweening=true
        self.t=tween(0.2,self.nowColor,{r=self.color.x,g=self.color.g,b=self.color.b},tween.easing.linear,function() self.isTweening=false end)
    elseif self.state==false and not self.isTweening then
        self.isTweening=true
        self.t=tween(0.2,self.nowColor,{r=self.backColor.x,g=self.backColor.g,b=self.backColor.b},tween.easing.linear,function() self.isTweening=false end)
    end
end

function UISwitch:touched(touch)
    -- Codea does not automatically call this method
    if touch.state==BEGAN then
        if touch.x>self.x-26 and touch.x<self.x+26 and touch.y>self.y-16  and touch.y<self.y+16 then
            --print("pressed")
            if self.state==false then
                self.state=true
            else
                self.state=false
            end
        end
    end
end

--# TextButton
-- TextButton
-- Ver 1.31
-- Author:bk194232658

TextButton = class(BaseObject)

function TextButton:init(x,y,capital)
    BaseObject.init(self,x,y)
    self.backColor = color(255, 255, 255, 0)
    self.textColor = color(0, 0, 0, 255)
    self.pressedBackColor = color(0, 0, 0, 0)
    self.pressedTextColor = color(0, 0, 0, 112)
    self.unEnabledBackColor = color(255, 255, 255, 0)
    self.unEnabledTextColor = color(67, 67, 67, 100)
    self.font = nil
    self.fontSize = 30
    self.visible = true
    self.enabled = true
    self.clicked = nil
    self.posMode = CENTER
    -- self.alignment = UIConst.Alignment.Middle
    self.pressedOffset = 0.5
    self.pressed = false
    self.touchid = 0
    self.clip = false
    self:setCapital(capital)
end

function TextButton:draw()
    if self.visible == false then return end
    pushStyle()
    if self.clip then
        local x,y = self.x,self.y
        if self.posMode == CENTER then
            x,y = x - self.width / 2,y - self.height / 2
        end
        clip(x,y,self.width,self.height)
    end
    noStroke()
    textMode(CENTER)
    if self.font then
        font(self.font)
    else
        font("HelveticaNeue-Light")
    end
    fontSize(self.fontSize)
    textWrapWidth(0)
    textMode(CENTER)
    if self.posMode == CENTER then
        rectMode(CENTER)
    else
        rectMode(CORNER)
    end
    
    if self.pressed == false then
        if self.enabled then
            fill(self.backColor)
        else
            fill(self.unEnabledBackColor or self.backColor)
        end
        rect(self.x,self.y,self.width,self.height)
        if self.enabled then
            fill(self.textColor)
        else
            fill(self.unEnabledTextColor or self.textColor)
        end
        if self.posMode == CENTER then
            text(self.capital,self.x,self.y)
        else
            text(self.capital,self.x + self.width / 2,self.y + self.height / 2)
        end
    else
        if self.enabled then
            fill(self.pressedBackColor)
        else
            fill(self.unEnabledBackColor or self.pressedBackColor)
        end
        rect(self.x,self.y,self.width,self.height) 
        if self.enabled then
            fill(self.pressedTextColor)
        else
            fill(self.unEnabledTextColor or self.pressedTextColor)
        end
        if self.posMode == CENTER then
            text(self.capital,self.x + self.pressedOffset,self.y - self.pressedOffset)
        else
            text(self.capital,self.x + self.width / 2 + self.pressedOffset,self.y + self.height/2 - self.pressedOffset) 
        end
    end
    clip()
    popStyle()
end

function TextButton:touched(touch)
    if self.visible == false then 
        return false
    end
    local x,y,width,height = self.x,self.y,self.width,self.height
    if self.posMode == CENTER then
        x,y = x - width / 2,y - height / 2
    end
    local isInButton = touch.x >= x and touch.y >= y and 
                touch.x <= x + width and touch.y <= y + height
    if isInButton then 
        if self.enabled == false then
            return true
        end
        if touch.state == BEGAN and self.touchid == 0 then
            self.pressed = true
            self.touchid = touch.id
        elseif touch.state == ENDED then
            if self.clicked then self.clicked() end
            self.pressed = false
            self.touchid = 0
        end
        return true
    end
    if self.touchid == touch.id then
        if touch.state == ENDED then
            self.pressed = false
            self.touchid = 0
        elseif not isInButton then
            self.pressed = false
        end
        return true
    end
    return false
end

function TextButton:setCapital(capital)
    self.capital = capital or ""
    self:autoSize()
end

function TextButton:autoSize()
    fontSize(self.fontSize)
    self.width,self.height = textSize(self.capital)
    self.width,self.height = self.width + 20,self.height + 10
end

function TextButton:setFont(font,size)
    self.font = font or self.font
    self.fontSize = size or self.fontSize
    self:autoSize()
end

--# Main
-- Meme Ball
math.randomseed(os.time())
displayMode(FULLSCREEN)
supportedOrientations(LANDSCAPE_ANY)
-- Use this function to perform your initial setup
function setup()
    socket=Multiplayer()
    system={}
    system.music=1
    system.fx=1
    system.ballline=true
    system.funnyBall=false
    system.name="Write down your name.."
    classes={}
    classes.mode="startMenu"
    classes.settings=Settings()
    classes.startMenu=startMenu()
    classes.networkMenu=NetworkMenu()
    classes.wait=Waiting()
    music("Project:192000-29784013-",true)
    physics.gravity(0,0)
end

-- This function gets called once every frame
function draw()
    music.volume=system.music
    background(127, 127, 127, 255)
    -- This sets a dark background color 
    classes[classes.mode]:draw()
end

function touched(touch)
    classes[classes.mode]:touched(touch)
end

function keyboard(key)
    if classes.mode=="networkMenu" then
        classes[classes.mode]:keyboard(key)
    end
end

function collide(c)
    if classes.mode=="game" or classes.mode=="PvP" then
        classes[classes.mode]:collide(c)
    end
    if c.state==BEGAN then
        sound("Game Sounds One:Assembly 3",system.fx)
    end
end

--# startMenu

startMenu = class()

function startMenu:init()
    -- you can accept and set parameters here
    --self.nameBox=TextBox(WIDTH/2,HEIGHT/2,200,40,system.name)
    self.PvE=TextButton(WIDTH/2,HEIGHT/3,"PvE")
    self.PvE.clicked=function()
        classes.game=Game()
        classes.mode="game"
    end
    self.PvP=TextButton(WIDTH/3,HEIGHT/4,"PvP(Local)")
    self.PvP.clicked=function()
        classes.PvP=Game_PvP() 
        classes.mode="PvP"
    end
    self.Network=TextButton(WIDTH/1.5,HEIGHT/4,"PvP(Network)")
    self.Network.clicked=function()
        classes.mode="networkMenu"
    end
    self.settings=TextButton(WIDTH/2,HEIGHT/6,"Settings")
    self.settings.clicked=function()
        classes.mode="settings"
    end
    self.Buttons={self.PvE,self.PvP,self.settings,self.Network,--[[self.nameBox]]}
end

function startMenu:draw()
    -- Codea does not automatically call this method
    sprite("Project:Title",WIDTH/2,HEIGHT/2,WIDTH,HEIGHT)
    tint(0, 0, 0, 255)
    sprite("Cargo Bot:Made With Codea",WIDTH-170,30,300)
    noTint()
    for k,v in pairs(self.Buttons) do
        v:draw()
    end
end

function startMenu:touched(touch)
    for k,v in pairs(self.Buttons) do
        v:touched(touch)
    end
    -- Codea does not automatically call this method
end

--# Settings
Settings = class()

function Settings:init()
    -- you can accept and set parameters here
    self.back=TextButton(100,HEIGHT-50,"返回")
    self.back.clicked=function()
        classes.mode="startMenu"
    end
    self.music=UISlider(600,0,1,WIDTH/2+100,HEIGHT-150,600*system.music)
    self.music.num=system.music
    self.fx=UISlider(600,0,1,WIDTH/2+100,HEIGHT-200,600*system.fx)
    self.fx.num=system.fx
    self.ballline=UISwitch(WIDTH/2-200,HEIGHT-250)
    self.ballline.state=system.ballline
    self.funnyball=UISwitch(WIDTH/2+350,HEIGHT-250)
    self.funnyball.state=system.funnyBall
    self.Buttons={self.music,self.fx,self.ballline,self.back,self.funnyball}
end

function Settings:draw()
    print(self.fx.num)
    system.funnyBall=self.funnyball.state
    system.ballline=self.ballline.state
    system.music=self.music.num/3
    system.fx=self.fx.num/3
    -- Codea does not automatically call this method
    sprite("Project:Background",WIDTH/2,HEIGHT/2,WIDTH,HEIGHT)
    for k,v in pairs(self.Buttons) do
        v:draw()
    end
    fontSize(30)
    fill(0, 0, 0, 255)
    text("游戏设置",WIDTH/2,HEIGHT-50)
    fontSize(20)
    text("音乐音量",150,HEIGHT-150)
    text("FX音量",150,HEIGHT-200)
    text("辅助瞄准",150,HEIGHT-250)
    text("滑稽球",WIDTH/2+200,HEIGHT-250)
end

function Settings:touched(touch)
    -- Codea does not automatically call this method
    for k,v in pairs(self.Buttons) do
        v:touched(touch)
    end
end

--# Game
Game = class()

function Game:init()
    -- you can accept and set parameters here
    self.textspos={aty=HEIGHT-100,bty=100,isTweening=false}
    self.lose=0
    self.Edge=physics.body(CHAIN,true,vec2(0,0),vec2(WIDTH,0),vec2(WIDTH,HEIGHT),vec2(0,HEIGHT))
    self.Edge.categories={4}
    self.Edge.mask={0}
    self.nowFang=1
    self.P1={}
    self.P1.maxHP=1000
    self.P1.HP=1000
    self.P1.AT=200
    self.P1.ZZ=0
    self.P1.DEF=0
    self.P1.hitNum=1
    self.P1.body=physics.body(CIRCLE,30)
    self.P1.body.position=vec2(WIDTH/5,HEIGHT/2)
    self.P1.body.linearDamping=2
    self.P1.body.bullet=true
    self.P1.body.restitution=0.3
    self.P1.body.categories={0}
    self.P1.body.mask={0,4}
    self.P1.mode=1
    self.P1.isMoving=false
    self.P1.isLineing=false
    self.P1.attacked=false
    self.P2={}
    self.P2.maxHP=1000
    self.P2.HP=1000
    self.P2.AT=200
    self.P2.DEF=0
    self.P2.hitNum=1
    self.P2.body=physics.body(CIRCLE,30)
    self.P2.body.position=vec2(math.random(math.floor(WIDTH/5*4),WIDTH),math.random(0,HEIGHT))
    self.P2.body.linearDamping=2
    self.P2.body.bullet=true
    self.P2.body.restitution=0.3
    self.P2.body.categories={0}
    self.P2.body.mask={0,4}
    self.P2.mode=1
    self.P2.isMoving=false
    self.P2.isLineing=false
    self.P2.attacked=false
    self.P1HPBAR=ProcessBar(WIDTH/2,HEIGHT-60,WIDTH-50,50)
    self.P2HPBAR=ProcessBar(WIDTH/2,60,WIDTH-50,50)
    self.P2HPBAR.color=color(255, 0, 0, 142)
    self.GUIS={self.P1HPBAR,self.P2HPBAR}
    physics.continuous=true
end

function Game:draw()
    self.P1HPBAR.percentage=self.P1.HP/self.P1.maxHP
    self.P2HPBAR.percentage=self.P2.HP/self.P2.maxHP
    -- Codea does not automatically call this method
    sprite("Project:Background",WIDTH/2,HEIGHT/2,WIDTH,HEIGHT)
    strokeWidth(5)
    stroke(0, 0, 0, 255)
    line(WIDTH/5,0,WIDTH/5,HEIGHT)
    line(WIDTH/5*4,0,WIDTH/5*4,HEIGHT)
    if self.nowFang==1 then
        self.textspos.atx=HEIGHT-100
        self.textspos.btx=100
        fill(255, 0, 0, 48)
        stroke(255, 0, 0, 163)
        ellipse(self.P1.body.x,self.P1.body.y,220)
        fill(125, 23, 165, 54)
        stroke(143, 22, 171, 120)
        ellipse(self.P2.body.x,self.P2.body.y,120)
        fill(0, 37, 255, 52)
        stroke(14, 0, 255, 114)
        ellipse(self.P2.body.x,self.P2.body.y,220)
        if self.P2.body.position:dist(self.P1.body.position)<=190 and CurrentTouch.state==BEGAN and self.P1.ZZ==0 then
            self.P1.ZZ=100
        end
    elseif self.nowFang==2 then
        self.textspos.atx=100
        self.textspos.btx=HEIGHT+100
        fill(255, 0, 0, 48)
        stroke(255, 0, 0, 163)
        ellipse(self.P2.body.x,self.P2.body.y,220)
        fill(125, 23, 165, 54)
        stroke(143, 22, 171, 120)
        ellipse(self.P1.body.x,self.P1.body.y,120)
        fill(0, 37, 255, 52)
        stroke(14, 0, 255, 114)
        ellipse(self.P1.body.x,self.P1.body.y,220)
        if self.P2.body.position:dist(self.P1.body.position)<=190 and self.P2.body.position:dist(self.P1.body.position)>=120 and CurrentTouch.state==BEGAN and self.P1.DEF==0 then
            self.P1.DEF=50
        elseif self.P2.body.position:dist(self.P1.body.position)<120 and CurrentTouch.state==BEGAN and self.P1.DEF==0 then
            self.P1.DEF=200
        end
    end
    tint(0, 0, 0, 185)
    sprite("Project:Shadow",self.P1.body.x+10,self.P1.body.y-10,70)
    sprite("Project:Shadow",self.P2.body.x+10,self.P2.body.y-10,70)
    noTint()
    if self.P1.isLineing and system.ballline then
        local dic=(vec2(CurrentTouch.x,CurrentTouch.y)-self.P1.body.position):normalize()
        stroke(0, 0, 0, 128)
        line(self.P1.body.x+dic.x*200,self.P1.body.y+dic.y*200,self.P1.body.x,self.P1.body.y)
    end
    if system.funnyBall then
        sprite("Project:Funny",self.P1.body.x,self.P1.body.y,65)
    else
        sprite("Project:BlueBall",self.P1.body.x,self.P1.body.y,60)
    end
    sprite("Project:RedBall",self.P2.body.x,self.P2.body.y,60)
    if self.P1.body.linearVelocity:dist(vec2(0,0))<=2 and self.nowFang==1 and self.P1.attacked then
        self.nowFang=2
        self.P1.hitNum=1
        self.P2.attacked=false
        self.P1.DEF=0
        self.P1.ZZ=0
    elseif self.P2.body.linearVelocity:dist(vec2(0,0))<=2 and self.nowFang==2 and self.P2.attacked then
        self.nowFang=1
        self.P2.hitNum=1
        self.P1.attacked=false
        self.P2.DEF=0
        self.P2.ZZ=0
    end
    for k,v in pairs(self.GUIS) do
        v:draw()
    end
    if self.P2.attacked==false and self.nowFang==2 then
        self.P2.body:applyForce((self.P1.body.position-self.P2.body.position)*1000)
        self.P2.attacked=true
    end
    if self.P1.HP<=0 then
        self.P1.HP=0
        physics.pause()
        self.lose=1
    elseif self.P2.HP<=0 then
        self.P2.HP=0
        physics.pause()
        self.lose=2
    end
    fill(0, 0, 0, 255)
    fontSize(100)
    if self.lose==1 then
        text("You Lose!",WIDTH/2,HEIGHT/2)
    elseif self.lose==2 then
        text("You Win!",WIDTH/2,HEIGHT/2)
    end
    fontSize(30)
    text("攻击方",WIDTH/2,self.textspos.aty)
    text("挨打方",WIDTH/2,self.textspos.bty)
end

function Game:touched(touch)
    -- Codea does not automatically call this method
    if self.P1.mode==1 and touch.x<=WIDTH/5 then
        if vec2(touch.x,touch.y):dist(self.P1.body.position)<=15 then
            self.P1.body.position=vec2(touch.x,touch.y)
        else
            self.P1.isMoving=true
            self.P1.body.position=(vec2(touch.x,touch.y)-self.P1.body.position):normalize()*15+self.P1.body.position
        end
    elseif (touch.x>WIDTH/5 or self.P1.mode==2) and not self.P1.isMoving and touch.state~=ENDED and self.nowFang==1 then
        self.P1.mode=2
        self.P1.isLineing=true
    elseif self.P1.mode==2 and touch.state==ENDED and self.nowFang==1 and not self.P1.attacked then
        self.P1.body:applyForce((vec2(touch.x,touch.y)-self.P1.body.position)*100)
        self.P1.attacked=true
    end
    if touch.state==ENDED then
        self.P1.isLineing=false
        self.P1.isMoving=false
    end
end

function Game:collide(c)
    if c.state==BEGAN and (c.bodyA==self.P1.body or c.bodyB==self.P1.body) and (c.bodyA==self.P2.body or c.bodyB==self.P2.body) then
        if self.nowFang==1 then
            self.P2.HP = self.P2.HP - (self.P1.AT-math.random(0,10))/self.P1.hitNum-self.P1.ZZ/self.P1.hitNum
            self.P1.hitNum = self.P1.hitNum + 1
        else
            self.P1.HP = self.P1.HP-(self.P2.AT-math.random(0,10))/self.P2.hitNum+self.P1.DEF/self.P2.hitNum
            self.P2.hitNum = self.P2.hitNum + 1
        end
    end
end

--# Game_PvP
Game_PvP = class()

function Game_PvP:init()
    -- you can accept and set parameters here
    self.time=300
    self.textspos={aty=HEIGHT-100,bty=100,isTweening=false}
    self.lose=0
    self.Edge=physics.body(CHAIN,true,vec2(0,0),vec2(WIDTH,0),vec2(WIDTH,HEIGHT),vec2(0,HEIGHT))
    self.Edge.categories={2}
    self.Edge.mask={1}
    self.nowFang=1
    self.P1={}
    self.P1.maxHP=1000
    self.P1.HP=1000
    self.P1.AT=200
    self.P1.ZZ=0
    self.P1.DEF=0
    self.P1.hitNum=1
    self.P1.body=physics.body(CIRCLE,30)
    self.P1.body.position=vec2(WIDTH/5,HEIGHT/2)
    self.P1.body.linearDamping=2
    self.P1.body.bullet=true
    self.P1.body.restitution=0.3
    self.P1.body.categories={1}
    self.P1.body.mask={1,2}
    self.P1.mode=1
    self.P1.isMoving=false
    self.P1.isLineing=false
    self.P1.attacked=false
    self.P2={}
    self.P2.maxHP=1000
    self.P2.HP=1000
    self.P2.AT=200
    self.P2.DEF=0
    self.P2.ZZ=0
    self.P2.hitNum=1
    self.P2.body=physics.body(CIRCLE,30)
    self.P2.body.position=vec2(WIDTH/5*4,HEIGHT/2)
    self.P2.body.linearDamping=2
    self.P2.body.bullet=true
    self.P2.body.restitution=0.3
    self.P2.body.categories={1}
    self.P2.body.mask={1,2}
    self.P2.mode=1
    self.P2.isMoving=false
    self.P2.isLineing=false
    self.P2.attacked=false
    self.P1HPBAR=ProcessBar(WIDTH/2,HEIGHT-60,WIDTH-50,50)
    self.P2HPBAR=ProcessBar(WIDTH/2,60,WIDTH-50,50)
    self.P2HPBAR.color=color(255, 0, 0, 142)
    self.GUIS={self.P1HPBAR,self.P2HPBAR}
    physics.continuous=true
end

function Game_PvP:draw()
    self.time = self.time - 1
    if self.time>0 then
        self.P1.mode=1
        self.P2.mode=1
    else
        self.P1.mode=2
        self.P2.mode=2
    end
    -- Codea does not automatically call this method
    self.P1HPBAR.percentage=self.P1.HP/self.P1.maxHP
    self.P2HPBAR.percentage=self.P2.HP/self.P2.maxHP
    -- Codea does not automatically call this method
    sprite("Project:Background",WIDTH/2,HEIGHT/2,WIDTH,HEIGHT)
    strokeWidth(5)
    stroke(0, 0, 0, 255)
    line(WIDTH/5,0,WIDTH/5,HEIGHT)
    line(WIDTH/5*4,0,WIDTH/5*4,HEIGHT)
    if self.nowFang==1 then
        self.textspos.atx=HEIGHT-100
        self.textspos.btx=100
        fill(255, 0, 0, 48)
        stroke(255, 0, 0, 163)
        ellipse(self.P1.body.x,self.P1.body.y,220)
        fill(125, 23, 165, 54)
        stroke(143, 22, 171, 120)
        ellipse(self.P2.body.x,self.P2.body.y,120)
        fill(0, 37, 255, 52)
        stroke(14, 0, 255, 114)
        ellipse(self.P2.body.x,self.P2.body.y,220)
        if self.P2.body.position:dist(self.P1.body.position)<=190 and CurrentTouch.state==BEGAN and CurrentTouch.x<WIDTH/2 and self.P1.ZZ==0 then
            self.P1.ZZ=100
        end
        if self.P2.body.position:dist(self.P1.body.position)<=190 and self.P2.body.position:dist(self.P1.body.position)>=120 and CurrentTouch.state==BEGAN and CurrentTouch.x>WIDTH/2 and self.P2.DEF==0 then
            self.P2.DEF=50
        elseif self.P2.body.position:dist(self.P1.body.position)<120 and CurrentTouch.state==BEGAN and self.P2.DEF==0 then
            self.P2.DEF=200
        end
    elseif self.nowFang==2 then
        self.textspos.atx=100
        self.textspos.btx=HEIGHT+100
        fill(255, 0, 0, 48)
        stroke(255, 0, 0, 163)
        ellipse(self.P2.body.x,self.P2.body.y,220)
        fill(125, 23, 165, 54)
        stroke(143, 22, 171, 120)
        ellipse(self.P1.body.x,self.P1.body.y,120)
        fill(0, 37, 255, 52)
        stroke(14, 0, 255, 114)
        ellipse(self.P1.body.x,self.P1.body.y,220)
        if self.P1.body.position:dist(self.P2.body.position)<=190 and CurrentTouch.state==BEGAN and CurrentTouch.x>WIDTH/2 and self.P2.ZZ==0 then
            self.P2.ZZ=100
        end
        if self.P2.body.position:dist(self.P1.body.position)<=190 and self.P2.body.position:dist(self.P1.body.position)>=120 and CurrentTouch.state==BEGAN and CurrentTouch.x<WIDTH/2 and self.P1.DEF==0 then
            self.P1.DEF=50
        elseif self.P2.body.position:dist(self.P1.body.position)<120 and CurrentTouch.state==BEGAN and CurrentTouch.x<WIDTH/2 and self.P1.DEF==0 then
            self.P1.DEF=200
        end
    end
    tint(0, 0, 0, 185)
    sprite("Project:Shadow",self.P1.body.x+10,self.P1.body.y-10,70)
    sprite("Project:Shadow",self.P2.body.x+10,self.P2.body.y-10,70)
    noTint()
    if self.P1.isLineing then
        local dic=(vec2(CurrentTouch.x,CurrentTouch.y)-self.P1.body.position):normalize()
        stroke(0, 0, 0, 128)
        line(self.P1.body.x+dic.x*200,self.P1.body.y+dic.y*200,self.P1.body.x,self.P1.body.y)
    end
    if self.P2.isLineing then
        local dic=(vec2(CurrentTouch.x,CurrentTouch.y)-self.P2.body.position):normalize()
        stroke(0, 0, 0, 128)
        line(self.P2.body.x+dic.x*200,self.P2.body.y+dic.y*200,self.P2.body.x,self.P2.body.y)
    end
    sprite("Project:BlueBall",self.P1.body.x,self.P1.body.y,60)
    sprite("Project:RedBall",self.P2.body.x,self.P2.body.y,60)
    if self.P1.body.linearVelocity:dist(vec2(0,0))<=2 and self.nowFang==1 and self.P1.attacked then
        self.nowFang=2
        self.P1.hitNum=1
        self.P2.attacked=false
        self.P1.DEF=0
        self.P1.ZZ=0
    elseif self.P2.body.linearVelocity:dist(vec2(0,0))<=2 and self.nowFang==2 and self.P2.attacked then
        self.nowFang=1
        self.P2.hitNum=1
        self.P1.attacked=false
        self.P2.DEF=0
        self.P2.ZZ=0
    end
    for k,v in pairs(self.GUIS) do
        v:draw()
    end
    if self.P1.HP<=0 then
        self.P1.HP=0
        physics.pause()
        self.lose=1
    elseif self.P2.HP<=0 then
        self.P2.HP=0
        physics.pause()
        self.lose=2
    end
    fill(0, 0, 0, 255)
    fontSize(100)
    if self.lose==1 then
        text("Player1 Win !",WIDTH/2,HEIGHT/2)
    elseif self.lose==2 then
        text("Player2 Win !",WIDTH/2,HEIGHT/2)
    end
    if math.ceil(self.time/60)>=0 then
        text(math.ceil(self.time/60),WIDTH/2,HEIGHT/2)
    end
    fontSize(30)
    text("攻击方",WIDTH/2,self.textspos.aty)
    text("挨打方",WIDTH/2,self.textspos.bty)
end

function Game_PvP:touched(touch)
    -- Codea does not automatically call this method
    if self.P1.mode==1 and touch.x<=WIDTH/5 then
        if vec2(touch.x,touch.y):dist(self.P1.body.position)<=15 then
            self.P1.body.position=vec2(touch.x,touch.y)
        else
            self.P1.isMoving=true
            self.P1.body.position=(vec2(touch.x,touch.y)-self.P1.body.position):normalize()*15+self.P1.body.position
        end
    elseif (self.P1.mode==2) and not self.P1.isMoving and touch.state~=ENDED and self.nowFang==1 then
        self.P1.mode=2
        self.P1.isLineing=true
    elseif self.P1.mode==2 and touch.state==ENDED and self.nowFang==1 and not self.P1.attacked then
        self.P1.body:applyForce((vec2(touch.x,touch.y)-self.P1.body.position)*100)
        self.P1.attacked=true
    end
    if touch.state==ENDED then
        self.P1.isLineing=false
        self.P1.isMoving=false
    end
    if self.P2.mode==1 and touch.x>=WIDTH/5*4 then
        if vec2(touch.x,touch.y):dist(self.P2.body.position)<=15 then
            self.P2.body.position=vec2(touch.x,touch.y)
        else
            self.P2.isMoving=true
            self.P2.body.position=(vec2(touch.x,touch.y)-self.P2.body.position):normalize()*15+self.P2.body.position
        end
    elseif (self.P2.mode==2) and not self.P2.isMoving and touch.state~=ENDED and self.nowFang==2 then
        self.P2.mode=2
        self.P2.isLineing=true
    elseif self.P2.mode==2 and touch.state==ENDED and self.nowFang==2 and not self.P2.attacked then
        self.P2.body:applyForce((vec2(touch.x,touch.y)-self.P2.body.position)*100)
        self.P2.attacked=true
    end
    if touch.state==ENDED then
        self.P2.isLineing=false
        self.P2.isMoving=false
    end
end

function Game_PvP:collide(c)
    if c.state==BEGAN and (c.bodyA==self.P1.body or c.bodyB==self.P1.body) and (c.bodyA==self.P2.body or c.bodyB==self.P2.body) then
        if self.nowFang==1 then
            self.P2.HP = self.P2.HP - (self.P1.AT-math.random(0,10))/self.P1.hitNum-self.P1.ZZ/self.P1.hitNum+self.P2.DEF/self.P1.hitNum
            self.P1.hitNum = self.P1.hitNum + 1
        else
            self.P1.HP = self.P1.HP-(self.P2.AT-math.random(0,10))/self.P2.hitNum+self.P1.DEF/self.P2.hitNum-self.P2.ZZ/self.P2.hitNum
            self.P2.hitNum = self.P2.hitNum + 1
        end
    end
end

--# NetworkMenu
NetworkMenu = class()

function NetworkMenu:init()
    -- you can accept and set parameters here
    self.createGame=TextButton(WIDTH/2-256,HEIGHT/2+100,"Create Game")
    self.createGame.clicked=function()
        socket:hostGame()
        classes.mode="wait"
    end
    self.searchGame=TextButton(WIDTH/2-256,HEIGHT/2-100,"Search Game")
    self.nameBox=TextBox(WIDTH/2,HEIGHT-150,300,40,system.name)
    self.IP=TextBox(WIDTH/2+256,HEIGHT/2+150,300,40,"")
    self.Post=TextBox(WIDTH/2+256,HEIGHT/2+50,300,40,"")
    self.join=TextButton(WIDTH/2+256,HEIGHT/2-50,"Join Game")
    self.Buttons={self.createGame,self.searchGame,self.nameBox,self.IP,self.Post,self.join}
end

function NetworkMenu:draw()
    -- Codea does not automatically call this method
    sprite("Project:Background",WIDTH/2,HEIGHT/2,WIDTH,HEIGHT)
    strokeWidth(2)
    stroke(0, 0, 0, 255)
    line(WIDTH/2,0,WIDTH/2,HEIGHT)
    fill(0, 0, 0, 255)
    fontSize(40)
    text("Local Wi-Fi",WIDTH/2-256,HEIGHT-50)
    text("IP and Post",WIDTH/2+256,HEIGHT-50)
    fontSize(20)
    text("IP",WIDTH/2+256,HEIGHT/2+190)
    text("Port",WIDTH/2+256,HEIGHT/2+90)
    for k,v in pairs(self.Buttons) do
        v:draw()
    end
end

function NetworkMenu:touched(touch)
    -- Codea does not automatically call this method
    for k,v in pairs(self.Buttons) do
        v:touched(touch)
    end
end

function NetworkMenu:keyboard(key)
    self.nameBox:keyboard(key)
    self.IP:keyboard(key)
    self.Post:keyboard(key)
end

--# Waiting
Waiting = class()

function Waiting:init()
    -- you can accept and set parameters here
    
end

function Waiting:draw()
    -- Codea does not automatically call this method
    sprite("Project:Background",WIDTH/2,HEIGHT/2,WIDTH,HEIGHT)
    text("Connect to "..socket.my_ip..":"..socket.my_port,WIDTH/2,HEIGHT/2+100)
    text("Waiting for other players..",WIDTH/2,HEIGHT/2-100)
end

function Waiting:touched(touch)
    -- Codea does not automatically call this method
end
